import patchVnode from "./patchVnode";
import createElement from "./createElement";
/**
 * 
 * @param {*} oldVnode 
 * @param {*} newVnode 
 * @returns 
 */
export function isSameNode(oldVnode,newVnode){
    return oldVnode.sel === newVnode.sel && oldVnode.key === newVnode.key
}

/**
 * 
 * @param {*} oldElm 
 * @param {*} oldCh 
 * @param {*} newCh 
 */
export default function updateVnode(oldElm, oldCh, newCh){
    let newStartIdx = 0; // 新前指针
    let newEndIdx = newCh.length - 1; // 新后指针
    let oldStartIdx = 0; // 旧前指针
    let oldEndIdx = oldCh.length - 1; // 旧后指针


    let newStartVNode = newCh[newStartIdx] // 新前虚拟节点
    let newEndVNode = newCh[newEndIdx] // 新后虚拟节点
    let oldStarVNode = oldCh[oldStartIdx] // 旧前虚拟节点
    let oldEndVNode = oldCh[oldEndIdx] // 旧后虚拟节点
    
    let keyMap = null;  // 缓存所有老节点中的key 

    while(newStartIdx <= newEndIdx && oldStartIdx <= oldEndIdx){
        // 首先应该不是判断四种命中，而是略过已经加了undefined标记的项
        if (oldStarVNode === null || oldCh[oldStartIdx] === undefined) {
            oldStarVNode = oldCh[++oldStartIdx];
        } else if (oldEndVNode === null || oldCh[oldEndIdx] === undefined) {
            oldEndVNode = oldCh[--oldEndIdx];
        } else if (newStartVNode === null || newCh[newStartIdx] === undefined) {
            newStartVNode = newCh[++newStartIdx];
        } else if (newEndVNode === null || newCh[newEndIdx] === undefined) {
            newEndVNode = newCh[--newEndIdx];
        } else if(isSameNode(oldStarVNode,newStartVNode)){ // 命中新前与旧前
            // 命中此种方式，新前与旧前指针需要同时往下移
            console.log('命中新前与旧前');
            patchVnode(oldStarVNode,newStartVNode)
            newStartVNode = newCh[++newStartIdx]
            oldStarVNode = oldCh[++oldStartIdx]
        }else if(isSameNode(oldEndVNode,newEndVNode)){ // 命中新后与旧后
            // 命中新后与旧后方式 新后与旧后指针需要同时往上移动
            console.log('命中新后与旧后');
            patchVnode(oldEndVNode,newEndVNode)
            newEndVNode = newCh[--newEndIdx]
            oldEndVNode = oldCh[--oldEndIdx]
        }else if(isSameNode(oldStarVNode,newEndVNode)){ // 命中新后与旧前
            // 命中此种方式，需要将 旧前指向的节点 插入到旧后之后
            console.log('命中新后与旧前');
            patchVnode(oldStarVNode,newEndVNode)
            oldElm.insertBefore(oldStarVNode.elm,oldEndVNode.elm.nextSibling)
            oldStarVNode = oldCh[++oldStartIdx]
            newEndVNode = newCh[--newEndIdx]
        }else if(isSameNode(oldEndVNode,newStartVNode)){ // 命中新前与旧后
            // 命中此种方式，需要将旧后指向的节点 插入到旧前之前
            console.log('命中新前与旧后');
            patchVnode(oldEndVNode,newStartVNode)
            oldElm.insertBefore(oldEndVNode.elm,oldStarVNode.elm)
            oldEndVNode = oldCh[--oldEndIdx]
            newStartVNode = newCh[++newStartIdx]
        }else{
            // 四种命中都没有命中
            if(!keyMap){
                keyMap = {}
                for(let i = oldStartIdx; i <= oldEndIdx; i++ ){
                    const key = oldCh[i].key
                    if(key!=undefined){
                        keyMap[key] = i
                    }
                }
            }

            // 寻找当前项‘新前’在keyMap中映射的序号
            const idxInOld = keyMap[newStartVNode.key]
            console.log(keyMap);
            if(idxInOld === undefined){
                // 如果没有找到 那就说明这是一个新的节点直接插入到旧前之前
                oldElm.insertBefore(createElement(newStartVNode),oldStarVNode.elm)
            }else{
                // debugger
                // 说明不是全新的节点 需要移动
                const elmToMove = oldCh[idxInOld];
                patchVnode(elmToMove,newStartVNode)
                oldCh[idxInOld] = undefined

                oldElm.insertBefore(elmToMove.elm,oldStarVNode.elm)
            }
            // newStartIdx++
            newStartVNode = [++newStartIdx]
        }
    }

    if(newStartIdx <= newEndIdx){ 
        // 新的头小于新的尾，证明新节点中还有未处理完的节点
        
        // before的目的是为了判断是在旧前还是旧后插入，如果为null则是在最后追加，如果不为null则在前增加
        const before = oldCh[oldStartIdx] === undefined?null:oldCh[oldStartIdx].elm
        
        // 环遍历创建旧前和旧后之间的节点，将新增的节点创建出来插入到旧前之前
        for(let i = newStartIdx; i <= newEndIdx; i++){
            oldElm.insertBefore(createElement(newCh[i]),before)
        }
    }else if(oldStartIdx <= oldEndIdx){
        // 旧的头小于旧的尾，证明旧节点中还有未处理完的节点
        // 循环遍历旧前和旧后之间的节点，并将他们移除
        for(let i = oldStartIdx; i <= oldEndIdx; i++){
            debugger
            if(oldCh[i]){
                oldElm.removeChild(oldCh[i].elm)
            }
        }
    }
}